package project.layer.ant;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import framework.events.EventBroker;

import project.data.DropOffIntention;
import project.data.PickUpIntention;
import project.events.antEvents.IntentionAntCreatedEvent;
import project.events.antEvents.IntentionAntDiedEvent;
import project.layer.agents.DropOffPointAgent;
import project.layer.agents.PickUpPointAgent;
import project.layer.agents.TruckAgent;
import project.layer.physical.Crossroad;
import project.layer.physical.Path;
import project.layer.physical.Road;

public class IntentionAnt extends Ant {
	
	private LinkedList<Integer> destinationIDs;
	private Path followedPath = new Path();
	private Path pathToFollow;
	private boolean isPickingUp = true;
	private boolean isFinished = false;
	private int indexOfCurrentCrossroad = 0;
	private int currentDestinationIndex;


	public void processAntTick(){
		
	}
	
	public List<Integer> getDestinationIDs(){
		return (LinkedList<Integer>)destinationIDs.clone();
	}
	
	public int getCurrentDestinationID(){
		return destinationIDs.get(currentDestinationIndex);
	}
	
	public void setCurrentDestinationToNextDestination(){
		currentDestinationIndex++;
	}
	
	public boolean currentDestinationIsLastDestination(){
		return currentDestinationIndex >= destinationIDs.size() - 1 ;
	}

	public LinkedList<Integer> getDestinations() {
		return destinationIDs;
	}

	public IntentionAnt(TruckAgent sendingAgent, Crossroad location, Path path) {
		super(sendingAgent, location);
		this.destinationIDs = new LinkedList<Integer>(path.getDestinations());
		this.pathToFollow = path.getClone();
		if(destinationIDs.size() % 2 == 1){
			isPickingUp = false;
		}
		else{
			isPickingUp = true;
		}
		followedPath.addCrossroadToFrontOfPath(location);
		this.currentDestinationIndex = 0;
		EventBroker.getEventBroker().notifyAll(new IntentionAntCreatedEvent(this));
		driveTillDestinations();
	}

		
	private void driveTillDestinations() {
		
		while(!isFinished){	
			
			if(isPickingUp){
				doPickupMove();
			}
			else{
				doDropOffMove();
			}
		}

	}
	
	private void increaseCurrentCrossroadIndex(){
		indexOfCurrentCrossroad++;
	}

	private void doDropOffMove() {

		if(!getLocation().hasDropOffPoint() || getLocation().getDropOffPoint().getCorrespondingAgent().getId() != getCurrentDestinationID()){
			increaseCurrentCrossroadIndex();
			
			Crossroad cr = pathToFollow.getListOfCrossroadsPath().get(indexOfCurrentCrossroad);
			setLocation(cr);
			followedPath.addCrossroadToPath(cr);
		}
		else{
			//Reached drop off point
			DropOffPointAgent dropoffPA = (DropOffPointAgent)getLocation().getDropOffPoint().getCorrespondingAgent();
			DropOffIntention dropOffIntent = new DropOffIntention(getSendingAgent().getId(), dropoffPA, dropoffPA.getPackageID());
			boolean accepted = dropoffPA.acceptOrRejectIntention(dropOffIntent);
			if(!accepted){
				AntLayer.getInstance().unregisterEvaporableData(dropOffIntent);
				
				die();
				this.isFinished=true;
			}
			followedPath.addToDestinations(dropoffPA.getId());
			
			
			if(!currentDestinationIsLastDestination()){
				//More destinations to visit
				setCurrentDestinationToNextDestination();
				isPickingUp = true;
			}
			else{
				//At end of path, report back
//				
				getSendingAgent().reportIntention(getFollowedPath());
				this.isFinished = true;
				die();
			}
			
		}
		
		
		
	}

	private void doPickupMove() {
		if(!getLocation().hasPickUpPoint() || getLocation().getPickUpPoint().getCorrespondingAgent().getId() != getCurrentDestinationID()){

			increaseCurrentCrossroadIndex();

			Crossroad cr = pathToFollow.getListOfCrossroadsPath().get(indexOfCurrentCrossroad);
		
			this.followedPath.addCrossroadToPath(cr);
			setLocation(cr);
		}
		else{

			//Delivering intention
			PickUpPointAgent pickupPA = (PickUpPointAgent)getLocation().getPickUpPoint().getCorrespondingAgent();
			PickUpIntention pickIntent = new PickUpIntention(getSendingAgent().getId(), pickupPA, this.followedPath.getTotalDistance());
			boolean accepted = pickupPA.acceptOrRejectIntention(pickIntent);
			if(!accepted){
				getSendingAgent().reportIntentionRejection(pickIntent, getDestinationIDs());
				AntLayer.getInstance().unregisterEvaporableData(pickIntent);
				die();
				this.isFinished = true;
			}
			else{
				followedPath.addToDestinations(pickupPA.getId());
				
				setCurrentDestinationToNextDestination();
				isPickingUp = false;
					
			}
			
			
			
		}
	}
	
	public Path getFollowedPath() {
		return followedPath.getClone();
	}


	
	
	
	
	

	@Override
	public TruckAgent getSendingAgent() {
		return (TruckAgent) this.sendingAgent;
	}

	@Override
	protected void createDieEvent() {
		EventBroker.getEventBroker().notifyAll(new IntentionAntDiedEvent(this));
		
	}

}
